module.exports = {
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    // setter 必须有对应的 getter，getter 可以没有对应的 setter
    'accessor-pairs': [
      2,
      {
        setWithoutGet: true,
        getWithoutSet: false
      }
    ],
    // 要求箭头函数的参数使用括号
    'arrow-parens': 0,
    // 箭头函数的箭头前后必须有空格
    'arrow-spacing': [
      2,
      {
        before: true,
        after: true
      }
    ],
    // case 的冒号前禁止有空格，冒号后必须有空格
    'switch-colon-spacing': [
      2,
      {
        after: true,
        before: false
      }
    ],
    // 模版字符串的 tag 之后禁止有空格，比如 tag`Hello World`
    'template-tag-spacing': [2, 'never'],
    // 代码块如果在一行内，那么大括号内的首尾必须有空格，比如 function () { alert('Hello') }
    'block-spacing': [2, 'always'],
    // 强制在代码块中使用一致的大括号风格
    'brace-style': [
      2,
      '1tbs',
      {
        allowSingleLine: true
      }
    ],
    // 要求使用驼峰命名法声明变量
    camelcase: [
      0,
      {
        properties: 'always'
      }
    ],
    // 逗号前禁止有空格，逗号后必须要有空格
    'comma-spacing': [
      2,
      {
        before: false,
        after: true
      }
    ],
    // 禁止 for 循环出现方向错误的循环，比如 for (i = 0; i < 10; i--)
    'for-direction': 2,
    // constructor 中必须有 super
    'constructor-super': 2,
    // if 后面必须要有 {，除非是单行 if
    curly: [2, 'multi-line', 'consistent'],
    // 链式调用的时候，点号必须放在第二行开头处，禁止放在第一行结尾处
    'dot-location': [2, 'property'],
    // 要求或禁止文件末尾存在空行 没必要限制 prettier会帮助我们处理
    'eol-last': 0,
    // 必须使用 === 或 !==，禁止使用 == 或 !=，与 null 比较时除外
    eqeqeq: [2, 'always', { null: 'ignore' }],
    // 数组的方法除了 forEach 之外，回调函数必须有返回值
    'array-callback-return': 2,
    // generator 的 * 前面禁止有空格，后面必须有空格
    'generator-star-spacing': [
      2,
      {
        before: false,
        after: true
      }
    ],
    // callback 中的 error 必须被处理 规则会形参是err或者error命名的
    'handle-callback-err': [2, '^(err|error)$'],
    // 缩进使用2个空格缩进
    indent: [
      2,
      2,
      {
        SwitchCase: 1,
        flatTernaryExpressions: true
      }
    ],
    // jsx 中的属性必须用双引号
    'jsx-quotes': [2, 'prefer-double'],
    // 对象字面量中冒号前面禁止有空格，后面必须有空格
    'key-spacing': [
      2,
      {
        beforeColon: false,
        afterColon: true,
        // 制在冒号前后只有一个空格
        mode: 'strict'
      }
    ],
    // 关键字前后必须有空格
    'keyword-spacing': [
      2,
      {
        before: true,
        after: true
      }
    ],
    // new 后面的类名必须首字母大写
    'new-cap': [
      2,
      {
        newIsCap: true,
        capIsNew: false
      }
    ],
    // new 后面的类必须有小括号
    'new-parens': 2,
    // 禁止出现难以理解的箭头函数，比如 let x = a => 1 ? 2 : 3
    'no-confusing-arrow': [
      2,
      {
        allowParens: true
      }
    ],
    // 禁止使用 Array 构造函数
    'no-array-constructor': 2,
    // 禁止使用 caller 或 callee（arguments.caller 和 arguments.callee）
    'no-caller': 2,
    // console 的使用很常见
    // 'no-console': 'off',
    // 禁止对定义过的 class 重新赋值
    'no-class-assign': 2,
    // // 禁止在测试表达式中使用赋值语句，除非这个赋值语句被括号包起来了
    'no-cond-assign': [2, 'except-parens'],
    // 禁止对使用 const 定义的常量重新赋值
    'no-const-assign': 2,
    'no-control-regex': 0,
    // 禁止对变量使用delete操作符
    'no-delete-var': 2,
    // 禁止在函数参数中出现重复名称的参数
    'no-dupe-args': 2,
    // 禁止重复定义类
    'no-dupe-class-members': 2,
    // 禁止在对象字面量中出现重复名称的键名
    'no-dupe-keys': 2,
    // 禁止在 switch 语句中出现重复测试表达式的 case
    'no-duplicate-case': 2,
    // 禁止在正则表达式中使用空的字符集 举例：/^abc[]/
    'no-empty-character-class': 2,
    // 禁止解构中出现空 {} 或 []
    'no-empty-pattern': 2,
    // 禁止使用 eval
    'no-eval': 2,
    // 禁止将 catch 的第一个参数 error 重新赋值
    'no-ex-assign': 2,
    // 禁止修改原生对象 如：Object.prototype.a = 'a'
    'no-extend-native': 2,
    // 禁止使用 foo == null 或 foo != null，必须使用 foo === null 或 foo !== null
    // foo == null 用于判断 foo 不是 undefined 并且不是 null，比较常用，故允许此写法
    'no-eq-null': 0,
    // 禁止出现没必要的 bind
    'no-extra-bind': 2,
    // 禁止不必要的布尔类型转换，比如 !! 或 Boolean 例如：if (!!foo) {}
    'no-extra-boolean-cast': 2,
    // 禁止函数表达式中出现多余的括号，比如 let foo = (function () { return 1 })
    'no-extra-parens': [2, 'functions'],
    // switch 的 case 内必须有 break, return 或 throw
    'no-fallthrough': 2,
    // 表示小数时，禁止省略 0，比如 .5
    'no-floating-decimal': 2,
    // 禁止将一个函数声明重新赋值，如：
    // function foo() {}
    // foo = bar
    'no-func-assign': 2,
    // 禁止在 setTimeout 或 setInterval 中传入字符串，如 setTimeout('alert("Hi!")', 100);
    'no-implied-eval': 2,
    // 禁止在 if 代码块内出现函数声明
    'no-inner-declarations': [2, 'both'],
    // 禁止在 RegExp 构造函数中出现非法的正则表达式
    'no-invalid-regexp': 2,
    // 禁止使用特殊空白符（比如全角空格），除非是出现在字符串、正则表达式或模版字符串中
    'no-irregular-whitespace': [
      2,
      {
        skipStrings: true,
        skipComments: false,
        skipRegExps: true,
        skipTemplates: true
      }
    ],
    // 禁止使用 __iterator__
    'no-iterator': 2,
    // 禁止 label 名称与定义过的变量重复
    'no-label-var': 2,
    // 禁止使用 label
    'no-labels': 2,
    // 禁止使用没必要的 {} 作为代码块
    'no-lone-blocks': 2,
    // 禁止混用空格和缩进
    'no-mixed-spaces-and-tabs': 2,
    // 禁止在代码后添加内联注释 内联注释很常用
    'no-inline-comments': 0,
    // 禁止使用位运算 没必要禁
    'no-bitwise': 0,
    // 禁止使用 continue，continue很常用
    'no-continue': 0,
    // 禁止混用不同的操作符，比如 let foo = a && b < 0 || c > 0 || d + 1 === 0
    // 太严格了，可以由使用者自己去判断如何混用操作符
    'no-mixed-operators': 0,
    // 回调函数嵌套禁止超过 3 层，多了请用 async await 替代
    'max-nested-callbacks': [2, 3],
    // 代码块嵌套的深度禁止超过 5 层
    'max-depth': [2, 5],
    // 函数的参数禁止超过5个， 再多在混乱难记
    'max-params': [2, 5],
    // 禁止出现连续的多个空格，除非是注释前，或对齐对象的属性、变量定义、import 等
    'no-multi-spaces': [
      2,
      {
        ignoreEOLComments: true,
        exceptions: {
          Property: true,
          BinaryExpression: false,
          VariableDeclarator: true,
          ImportDeclaration: true
        }
      }
    ],
    // 禁止使用 \ 来换行字符串
    'no-multi-str': 2,
    // 出现多个空行
    'no-multiple-empty-lines': [
      2,
      {
        max: 1,
        maxEOF: 1,
        maxBOF: 1
      }
    ],
    // 变量必须先定义后使用
    'no-use-before-define': [
      2,
      {
        functions: false,
        classes: false,
        variables: false
      }
    ],
    // 禁止重复 import 模块
    'no-duplicate-imports': 2,
    // 禁止解构时出现同样名字的的重命名，比如 let { foo: foo } = bar;
    'no-useless-rename': 2,
    // 禁止使用 var
    'no-var': 2,
    // 禁止对全局变量赋值 如：window = {}; Object = null;
    'no-global-assign': 2,
    // 禁止在 in 或 instanceof 操作符的左侧使用感叹号，如 if (!key in object)
    'no-unsafe-negation': 2,
    // 禁止直接 new Object
    'no-new-object': 2,
    // 禁止直接 new require('foo')
    'no-new-require': 2,
    // 禁止使用 new 来生成 Symbol
    'no-new-symbol': 2,
    // 禁止使用 new 来生成 String, Number 或 Boolean
    'no-new-wrappers': 2,
    // 禁止使用 new Function，比如 let x = new Function("a", "b", "return a + b");
    'no-new-func': 2,
    // 禁止将 Math, JSON 或 Reflect 直接作为函数调用
    'no-obj-calls': 2,
    // 禁止使用 0 开头的数字表示八进制数
    'no-octal': 2,
    // 禁止使用八进制的转义符
    'no-octal-escape': 2,
    // 禁止对 __dirname 或 __filename 使用字符串连接
    'no-path-concat': 2,
    // 禁止使用 __proto__
    'no-proto': 2,
    // 禁止重复定义变量
    'no-redeclare': 2,
    // 禁止在正则表达式中出现连续的空格，必须使用 /foo {3}bar/ 代替
    'no-regex-spaces': 2,
    // 禁止在 return 语句里赋值
    'no-return-assign': [2, 'always'],
    // 禁止将自己赋值给自己
    'no-self-assign': 2,
    // 禁止将自己与自己比较
    'no-self-compare': 2,
    // 禁止使用逗号操作符
    'no-sequences': 2,
    // 禁止使用保留字作为变量名
    'no-shadow-restricted-names': 2,
    // 函数名和执行它的括号之间禁止有空格
    'func-call-spacing': 2,
    // 禁止在数组中出现连续的逗号，如 let foo = [,,]
    'no-sparse-arrays': 2,
    // 禁止在 super 被调用之前使用 this 或 super
    'no-this-before-super': 2,
    // 禁止 throw 字面量，必须 throw 一个 Error 对象
    'no-throw-literal': 2,
    // 禁止行尾有空格
    'no-trailing-spaces': 2,
    // 用作对象的计算属性时，中括号内的首尾禁止有空格
    'computed-property-spacing': [2, 'never'],
    // 禁止在行首写逗号
    'comma-style': [2, 'last'],
    // 禁止使用未定义的变量
    'no-undef': [
      2,
      {
        typeof: false
      }
    ],
    // 禁止将 undefined 赋值给变量
    'no-undef-init': 2,
    // [1, 2, 3].forEach(baz);
    'no-unexpected-multiline': 2,
    // 循环内必须对循环条件的变量有修改
    'no-unmodified-loop-condition': 2,
    // 禁止可以表达为更简单结构的三元操作符
    'no-unneeded-ternary': [
      2,
      {
        defaultAssignment: false
      }
    ],
    // 禁止在 return, throw, break 或 continue 之后还有代码
    'no-unreachable': 2,
    // 禁止在 finally 中出现 return, throw, break 或 continue
    'no-unsafe-finally': 2,
    // 禁止将常量作为分支条件判断中的测试表达式，但允许作为循环条件判断中的测试表达式
    'no-constant-condition': [
      'error',
      {
        checkLoops: false
      }
    ],
    // 定义过的变量必须使用 有时开发中可能存在引入了一个方法 但不会立即使用
    // 在真正提交代码是 清除这个警告即可
    'no-unused-vars': [
      1,
      {
        vars: 'all',
        args: 'none'
      }
    ],
    // switch 语句必须有 default 太严格了
    'default-case': 0,
    // 不允许有空函数，除非是将一个空函数设置为某个项的默认值
    // ps 由于临时定义一个函数 可能不会立马编写函数代码体 可以在函数内部 定义一个注释临时解决这个错误
    'no-empty-function': [
      'error',
      {
        allow: ['functions', 'arrowFunctions']
      }
    ],
    // 禁止出现空代码块，允许 catch 为空代码块
    'no-empty': [
      2,
      {
        allowEmptyCatch: true
      }
    ],
    // 禁止出现没必要的 call 或 apply
    'no-useless-call': 2,
    // 禁止出现没必要的字符串连接
    'no-useless-concat': 2,
    // 禁止使用 tabs
    'no-tabs': 2,
    // 禁止出现没必要的计算键名，比如 let a = { ['0']: 0 };
    'no-useless-computed-key': 2,
    // 禁止出现没必要的 constructor，比如 constructor(value) { super(value) }
    'no-useless-constructor': 2,
    'no-useless-escape': 0,
    // 禁止属性前有空格，比如 foo. bar()
    'no-whitespace-before-property': 2,
    // 禁止使用 with
    'no-with': 2,
    // 限制语句之间的空行规则，比如变量定义完之后必须要空行 没必要限制
    'padding-line-between-statements': 0,
    // 变量申明必须每行一个
    'one-var-declaration-per-line': [2, 'always'],
    // 禁止变量申明时用逗号一次申明多个
    'one-var': [2, 'never'],
    // 强制操作符使用一致的换行符风格
    'operator-linebreak': [
      2,
      'after',
      {
        overrides: {
          '?': 'before',
          ':': 'before'
        }
      }
    ],
    // 禁止 if 后面不加大括号而写两行代码
    'nonblock-statement-body-position': [
      2,
      'beside',
      {
        overrides: {
          while: 'below'
        }
      }
    ],
    // 禁止块语句和类的开始或末尾有空行
    'padded-blocks': [2, 'never'],
    // 必须使用单引号，禁止使用双引号
    quotes: [
      2,
      'single',
      {
        avoidEscape: true,
        allowTemplateLiterals: true
      }
    ],
    // 一行有多个语句时，分号前面禁止有空格，分号后面必须有空格
    'semi-spacing': [
      2,
      {
        before: false,
        after: true
      }
    ],
    // 结尾必须有分号
    semi: [
      2,
      'always',
      {
        omitLastInOneLineBlock: true
      }
    ],
    // 分号必须写在行尾，禁止在行首出现
    'semi-style': [2, 'last'],
    // if, function 等的大括号之前必须要有空格，比如 if (a)
    'space-before-blocks': [2, 'always'],
    // 要求对象属性按序排列 没必要限制
    'sort-keys': 0,
    // function的小括号空格规则
    'space-before-function-paren': [
      2,
      {
        anonymous: 'ignore',
        named: 'never',
        asyncArrow: 'always'
      }
    ],
    // 小括号内的首尾禁止有空格
    'space-in-parens': [2, 'never'],
    // 操作符左右必须有空格，比如 let sum = 1 + 2;
    'space-infix-ops': 2,
    // @fixable new, typeof 等后面必须有空格，++, -- 等禁止有空格，比如：
    // let foo = new Person();
    // bar = bar++;
    'space-unary-ops': [
      2,
      {
        words: true,
        nonwords: false
      }
    ],
    // 注释的空白规则
    'spaced-comment': [
      2,
      'always',
      {
        markers: ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','],
        block: {
          exceptions: ['*'],
          balanced: true
        }
      }
    ],
    // 模板字符串中 ${name} 内的首尾禁止有空格
    'template-curly-spacing': [2, 'never'],
    // 必须使用 isNaN(foo) 而不是 foo === NaN
    'use-isnan': 2,
    // typeof 表达式比较的对象必须是 'undefined', 'object', 'boolean', 'number', 'string', 'function' 或 'symbol'
    'valid-typeof': 2,
    // 立即执行的函数必须符合如下格式 (function () { alert('Hello') })()
    'wrap-iife': [
      2,
      'inside',
      {
        functionPrototypeMethods: true
      }
    ],
    // yield* 后面必须要有空格
    'yield-star-spacing': [2, 'after'],
    // 必须使用 if (foo === 5) 而不是 if (5 === foo)
    yoda: [
      2,
      'never',
      {
        onlyEquality: true
      }
    ],
    // 不被修改的值 必须使用const声明 没必要限制
    'prefer-const': 0,
    // 对象字面量只有一行时，大括号内的首尾必须有空格
    'object-curly-spacing': [
      2,
      'always',
      {
        arraysInObjects: true,
        objectsInObjects: false
      }
    ],
    // 数组的括号内的前后禁止有空格
    'array-bracket-spacing': [2, 'never'],
    // 要求使用剩余参数 而不是arguments
    'prefer-rest-params': 2,
    // 将prettier的代码格式化集成进eslint的rules中
    // 'prettier/prettier': [
    //   2,
    //   {
    //     printWidth: 100,
    //     tabWidth: 2,
    //     useTabs: false,
    //     semi: true,
    //     singleQuote: true,
    //     quoteProps: 'as-needed',
    //     bracketSpacing: true,
    //     trailingComma: 'none',
    //     jsxBracketSameLine: false,
    //     jsxSingleQuote: false,
    //     arrowParens: 'avoid',
    //     insertPragma: false,
    //     requirePragma: false,
    //     proseWrap: 'never',
    //     htmlWhitespaceSensitivity: 'strict',
    //     endOfLine: 'auto',
    //     rangeStart: 0,
    //     vueIndentScriptAndStyle: false
    //   },
    //   {
    //     usePrettierrc: false
    //   }
    // ],
    // 按照vue固定的属性顺序进行排列
    'vue/attributes-order': [
      2,
      {
        order: [
          'DEFINITION',
          'LIST_RENDERING',
          'CONDITIONALS',
          'RENDER_MODIFIERS',
          'GLOBAL',
          ['UNIQUE', 'SLOT'],
          'TWO_WAY_BINDING',
          'OTHER_DIRECTIVES',
          'OTHER_ATTR',
          'EVENTS',
          'CONTENT'
        ],
        alphabetical: false
      }
    ],
    // 属性的形式 禁止触发驼峰命名
    'vue/attribute-hyphenation': [2, 'always'],
    // 未使用的组件
    'vue/no-unused-components': 1,
    // 关闭组件命名规则
    'vue/multi-word-component-names': 'off'
    // '@typescript-eslint/no-unused-vars': 1,
    // '@typescript-eslint/no-empty-function': 1,
    // 禁止没有定义函数返回值
    // '@typescript-eslint/explicit-module-boundary-types': 0,
    // 禁止any类型
    // '@typescript-eslint/no-explicit-any': 0
  }
};
